单侧投影
有时候会遇到给元素设置单侧投影的情形。要想实现单侧投影,首先得了解box-shadow的工作原理。
平时使用box-shadow的方法是指定三个长度值和一个颜色值:
box-shadow: 2px 3px 4px rgba(0,0,0,.5);
此时,shadow是通过下面四个步骤绘制的:
- 以该元素相同的尺寸和位置,画一个rgba(0,0,0,.5)的矩形
- 把它向右移2px,向下移3px
- 使用高斯模糊算法(或者类似算法)将它进行4px的模糊处理。模糊算法本质上是在阴影边缘发生阴影色和纯色透明色之间的颜色过渡,其长度近似于模糊半径的两倍(这里是8px)
- 最后,将模糊后的矩形与原始元素的交集部分切除掉,因此模糊的部分看起来是在该元素的后面,其实是和原始元素位于同一层。
具体步骤如下图:
对于box-shadow: 2px 3px 4px rgba(0,0,0,.5);将在顶部看到1px的投影,左侧看到2px的投影,右侧看到6px的投影,底部看到7px的投影。
此时如果改变偏移量就可以把顶部和左侧隐藏起来,但是这样会导致露出的投影太过浓重,而且也不是单侧投影。 这时候就可以利用box-shadow的第四个参数来实现了。
底边投影
box-shadow的第四个参数被称作扩张半径。这个参数会根据指定值的正负去扩大或者缩小投影的尺寸。举例来说,一个-5px的扩张半径会把投影的宽度和高度减少10px(两边各5px)。
因此,设置一个负的扩张半径,其值刚好等于模糊半径,那么投影的尺寸就会与投影所属元素的尺寸完全一致。然后再通过偏移量进行单方向移动,就会产生单侧投影。比如下面的底边投影:
<div class="shadow-b"></div>
div{
margin: 20px;
width: 10em;
height: 6em;
background: #fb3;
display: inline-block;
}
.shadow-b{
box-shadow: 0 6px 4px -4px black;
}

邻边投影
对于邻边投影:
- 不能把投影缩小的太小,只需要把阴影藏进一侧,另一侧自然露出。可以设置扩张半径为模糊半径相反值的一半
- 指定两个偏移量,它们的值需要大于或者等于模糊半径的一半,这有这有才能把投影“藏进”元素内部。(其实是切割掉)
代码如下:
.shadow-d{
box-shadow: 3px 3px 6px -3px black;
}

双侧投影
双侧投影很简单,利用单侧投影的原理,模拟两条投影即可:
.shadow-e{
box-shadow: 5px 0 5px -5px black,
-5px 0 5px -5px black;
}

不规则投影
给一个矩形元素或者其他能用border-radius生成的形状(圆或者椭圆)加投影时,不会出现问题。
但是当给一个有伪元素装饰的元素或者虚线边框添加投影,或者给具有切角效果的元素添加投影时,会出现透明的效果。如下图:

这个问题可以用filter属性来解决,设置阴影滤镜drop-shadow,它接收的参数基本与box-shadow一样,但不包括扩展半径和inset关键字。也不支持逗号分隔的多层投影语法。
因此修改下上面的代码:
HTML:
<div class="drop-a"></div>
<div class="drop-b"></div>
<div class="drop-c"></div>
CSS:
.drop-a,.drop-b,.drop-c{
position: relative;
/*box-shadow: 2px 2px 10px rgba(0,0,0,0.5);*/
-webkit-filter: drop-shadow(.3em .3em .3em rgba(0,0,0,0.5));
}
.drop-a::before{
content: "";
position: absolute;
width: 0;
height: 0;
top: 1em;
right: -1em;
border: 1em solid transparent;
border-left-color: #fb3;
border-right-width: 0;
}
.drop-b{
background: transparent;
box-sizing: border-box;
border: .5em dashed #fb3;
}
.drop-c{
border: .5em solid #58a;
border-image: 1 url('data:image/svg+xml,\
<svg xmlns="http://www.w3.org/2000/svg"\
width="3" height="3" fill="%23fb3">\
<polygon points="0,1 1,0 2,0 3,1 3,2 2,3 1,3 0,2"/>\
</svg>');
background-clip: padding-box;
box-sizing: border-box;
}

今天发烧,就不多写了,可能通篇文章逻辑有些问题…